home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / GLUT / progs / examples / dinoball.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  9KB  |  330 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1994.  */
  3.  
  4. /* This program is freely distributable without licensing fees 
  5.    and is provided without guarantee or warrantee expressed or 
  6.    implied. This program is -not- in the public domain. */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <math.h>       /* for cos(), sin(), and sqrt() */
  12. #include <GL/glu.h>
  13. #include <GL/glut.h>
  14.  
  15. typedef enum {
  16.   RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
  17.   LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE, DINOSAUR
  18. } displayLists;
  19.  
  20. GLfloat angle = -150;   /* in degrees */
  21. GLfloat xloc = 0, yloc = 0, zloc = 0;
  22. GLboolean doubleBuffer = GL_TRUE, iconic = GL_FALSE, keepAspect = GL_FALSE;
  23. int moving, begin;
  24. int W = 300, H = 300;
  25. GLdouble bodyWidth = 2.0;
  26. int newModel = 1;
  27. /* *INDENT-OFF* */
  28. GLfloat body[][2] = { {0, 3}, {1, 1}, {5, 1}, {8, 4}, {10, 4}, {11, 5},
  29.   {11, 11.5}, {13, 12}, {13, 13}, {10, 13.5}, {13, 14}, {13, 15}, {11, 16},
  30.   {8, 16}, {7, 15}, {7, 13}, {8, 12}, {7, 11}, {6, 6}, {4, 3}, {3, 2},
  31.   {1, 2} };
  32. GLfloat arm[][2] = { {8, 10}, {9, 9}, {10, 9}, {13, 8}, {14, 9}, {16, 9},
  33.   {15, 9.5}, {16, 10}, {15, 10}, {15.5, 11}, {14.5, 10}, {14, 11}, {14, 10},
  34.   {13, 9}, {11, 11}, {9, 11} };
  35. GLfloat leg[][2] = { {8, 6}, {8, 4}, {9, 3}, {9, 2}, {8, 1}, {8, 0.5}, {9, 0},
  36.   {12, 0}, {10, 1}, {10, 2}, {12, 4}, {11, 6}, {10, 7}, {9, 7} };
  37. GLfloat eye[][2] = { {8.75, 15}, {9, 14.7}, {9.6, 14.7}, {10.1, 15},
  38.   {9.6, 15.25}, {9, 15.25} };
  39. GLfloat lightZeroPosition[] = {10.0, 4.0, 10.0, 1.0};
  40. GLfloat lightZeroColor[] = {0.8, 1.0, 0.8, 1.0}; /* green-tinted */
  41. GLfloat lightOnePosition[] = {-1.0, -2.0, 1.0, 0.0};
  42. GLfloat lightOneColor[] = {0.6, 0.3, 0.2, 1.0}; /* red-tinted */
  43. GLfloat skinColor[] = {0.1, 1.0, 0.1, 1.0}, eyeColor[] = {1.0, 0.2, 0.2, 1.0};
  44. /* *INDENT-ON* */
  45.  
  46. void
  47. extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize,
  48.   GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
  49. {
  50.   static GLUtriangulatorObj *tobj = NULL;
  51.   GLdouble vertex[3], dx, dy, len;
  52.   int i;
  53.   int count = dataSize / (2 * sizeof(GLfloat));
  54.  
  55.   if (tobj == NULL) {
  56.     tobj = gluNewTess();  /* create and initialize a GLU
  57.                              polygon * * tesselation object */
  58.     gluTessCallback(tobj, GLU_BEGIN, glBegin);
  59.     gluTessCallback(tobj, GLU_VERTEX, glVertex2fv);  /* semi-tricky 
  60.                                                       */
  61.     gluTessCallback(tobj, GLU_END, glEnd);
  62.   }
  63.   glNewList(side, GL_COMPILE);
  64.   glShadeModel(GL_SMOOTH);  /* smooth minimizes seeing
  65.                                tessellation */
  66.   gluBeginPolygon(tobj);
  67.   for (i = 0; i < count; i++) {
  68.     vertex[0] = data[i][0];
  69.     vertex[1] = data[i][1];
  70.     vertex[2] = 0;
  71.     gluTessVertex(tobj, vertex, data[i]);
  72.   }
  73.   gluEndPolygon(tobj);
  74.   glEndList();
  75.   glNewList(edge, GL_COMPILE);
  76.   glShadeModel(GL_FLAT);  /* flat shade keeps angular hands
  77.                              from being * * "smoothed" */
  78.   glBegin(GL_QUAD_STRIP);
  79.   for (i = 0; i <= count; i++) {
  80.     /* mod function handles closing the edge */
  81.     glVertex3f(data[i % count][0], data[i % count][1], 0.0);
  82.     glVertex3f(data[i % count][0], data[i % count][1], thickness);
  83.     /* Calculate a unit normal by dividing by Euclidean
  84.        distance. We * could be lazy and use
  85.        glEnable(GL_NORMALIZE) so we could pass in * arbitrary
  86.        normals for a very slight performance hit. */
  87.     dx = data[(i + 1) % count][1] - data[i % count][1];
  88.     dy = data[i % count][0] - data[(i + 1) % count][0];
  89.     len = sqrt(dx * dx + dy * dy);
  90.     glNormal3f(dx / len, dy / len, 0.0);
  91.   }
  92.   glEnd();
  93.   glEndList();
  94.   glNewList(whole, GL_COMPILE);
  95.   glFrontFace(GL_CW);
  96.   glCallList(edge);
  97.   glNormal3f(0.0, 0.0, -1.0);  /* constant normal for side */
  98.   glCallList(side);
  99.   glPushMatrix();
  100.   glTranslatef(0.0, 0.0, thickness);
  101.   glFrontFace(GL_CCW);
  102.   glNormal3f(0.0, 0.0, 1.0);  /* opposite normal for other side 
  103.                                */
  104.   glCallList(side);
  105.   glPopMatrix();
  106.   glEndList();
  107. }
  108.  
  109. void
  110. makeDinosaur(void)
  111. {
  112.   GLfloat bodyWidth = 3.0;
  113.  
  114.   extrudeSolidFromPolygon(body, sizeof(body), bodyWidth,
  115.     BODY_SIDE, BODY_EDGE, BODY_WHOLE);
  116.   extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4,
  117.     ARM_SIDE, ARM_EDGE, ARM_WHOLE);
  118.   extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2,
  119.     LEG_SIDE, LEG_EDGE, LEG_WHOLE);
  120.   extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2,
  121.     EYE_SIDE, EYE_EDGE, EYE_WHOLE);
  122.   glNewList(DINOSAUR, GL_COMPILE);
  123.   glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
  124.   glCallList(BODY_WHOLE);
  125.   glPushMatrix();
  126.   glTranslatef(0.0, 0.0, bodyWidth);
  127.   glCallList(ARM_WHOLE);
  128.   glCallList(LEG_WHOLE);
  129.   glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
  130.   glCallList(ARM_WHOLE);
  131.   glTranslatef(0.0, 0.0, -bodyWidth / 4);
  132.   glCallList(LEG_WHOLE);
  133.   glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
  134.   glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
  135.   glCallList(EYE_WHOLE);
  136.   glPopMatrix();
  137.   glEndList();
  138. }
  139.  
  140. void
  141. recalcModelView(void)
  142. {
  143.   glPopMatrix();
  144.   glPushMatrix();
  145.   glTranslatef(xloc, yloc, zloc);
  146.   glRotatef(angle, 0.0, 1.0, 0.0);
  147.   glTranslatef(-8, -8, -bodyWidth / 2);
  148.   newModel = 0;
  149. }
  150.  
  151. void
  152. redraw(void)
  153. {
  154.   if (newModel)
  155.     recalcModelView();
  156.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  157.   glCallList(DINOSAUR);
  158.   glutSwapBuffers();
  159. }
  160.  
  161. void
  162. mouse(int button, int state, int x, int y)
  163. {
  164.   if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
  165.     moving = 1;
  166.     begin = x;
  167.   }
  168.   if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
  169.     moving = 0;
  170.   }
  171. }
  172.  
  173. void
  174. motion(int x, int y)
  175. {
  176.   if (moving) {
  177.     angle = angle + (x - begin);
  178.     begin = x;
  179.     newModel = 1;
  180.     glutPostRedisplay();
  181.   }
  182. }
  183.  
  184. void
  185. tablet(int x, int y)
  186. {
  187.   xloc = ((GLfloat) x) / 500 - 4;
  188.   yloc = ((GLfloat) y) / 1000 - 2;
  189.   newModel = 1;
  190.   glutPostRedisplay();
  191. }
  192.  
  193. int xt = 1, yt = 1, zt = 1, xr = 1;
  194.  
  195. void
  196. translate(int x, int y, int z)
  197. {
  198.   GLfloat newz;
  199.  
  200.   if(xt) xloc += ((GLfloat)x) / 100;
  201.   if(yt) yloc += ((GLfloat)y) / 100;
  202.   if(zt) {
  203.     newz = zloc - ((GLfloat)z) / 100;
  204.     if(newz > -60.0 && newz < 13.0) zloc = newz;
  205.   }
  206.   newModel = 1;
  207.   glutPostRedisplay();
  208. }
  209.  
  210. void
  211. rotate(int x, int y, int z)
  212. {
  213.   if(xr) {
  214.     angle += x / 2.0;
  215.     newModel = 1;
  216.     glutPostRedisplay();
  217.   }
  218. }
  219.  
  220. void
  221. button(int button, int state)
  222. {
  223.   if(state == GLUT_DOWN) {
  224.     switch(button) {
  225.     case 1:
  226.       xt = yt = zt = xr = 1;
  227.       break;
  228.     case 5:
  229.       xt = 1; yt = zt = xr = 0;
  230.       break;
  231.     case 6:
  232.       yt = 1; xt = zt = xr = 0;
  233.       break;
  234.     case 7:
  235.       zt = 1; xt = yt = xr = 0;
  236.       break;
  237.     case 8:
  238.       xr = 1; xt = yt = zt = 0;
  239.       break;
  240.     case 9:
  241.       xloc = yloc = zloc = 0;
  242.       newModel = 1;
  243.       glutPostRedisplay();
  244.       break;
  245.     }
  246.   }
  247. }
  248.  
  249. void
  250. dials(int dial, int value)
  251. {
  252.   if(dial == 0) {
  253.     angle = value / 10.0;
  254.     newModel = 1;
  255.     glutPostRedisplay();
  256.   }
  257. }
  258.  
  259. GLboolean lightZeroSwitch = GL_TRUE, lightOneSwitch = GL_TRUE;
  260.  
  261. void
  262. controlLights(int value)
  263. {
  264.   switch (value) {
  265.   case 1:
  266.     lightZeroSwitch = !lightZeroSwitch;
  267.     if (lightZeroSwitch) {
  268.       glEnable(GL_LIGHT0);
  269.     } else {
  270.       glDisable(GL_LIGHT0);
  271.     }
  272.     break;
  273.   case 2:
  274.     lightOneSwitch = !lightOneSwitch;
  275.     if (lightOneSwitch) {
  276.       glEnable(GL_LIGHT1);
  277.     } else {
  278.       glDisable(GL_LIGHT1);
  279.     }
  280.     break;
  281.   }
  282.   glutPostRedisplay();
  283. }
  284.  
  285. int
  286. main(int argc, char **argv)
  287. {
  288.   glutInit(&argc, argv);
  289.   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);
  290.   glutCreateWindow("dinoball (Spaceball demo)");
  291.   glutDisplayFunc(redraw);
  292.   glutMouseFunc(mouse);
  293.   glutMotionFunc(motion);
  294.   glutTabletMotionFunc(tablet);
  295.   glutSpaceballMotionFunc(translate);
  296.   glutSpaceballRotateFunc(rotate);
  297.   glutSpaceballButtonFunc(button);
  298.   glutDialsFunc(dials);
  299.   glutCreateMenu(controlLights);
  300.   glutAddMenuEntry("Toggle right light", 1);
  301.   glutAddMenuEntry("Toggle left light", 2);
  302.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  303.   makeDinosaur();
  304.   glEnable(GL_CULL_FACE);
  305.   glEnable(GL_DEPTH_TEST);
  306.   glEnable(GL_LIGHTING);
  307.   glMatrixMode(GL_PROJECTION);
  308.   gluPerspective( /* field of view in degree */ 40.0,  /* aspect 
  309.                                                           ratio 
  310.                                                         */ 1.0,
  311.     /* Z near */ 1.0, /* Z far */ 100.0);
  312.   glMatrixMode(GL_MODELVIEW);
  313.   gluLookAt(0.0, 0.0, 30.0,  /* eye is at (0,0,30) */
  314.     0.0, 0.0, 0.0,      /* center is at (0,0,0) */
  315.     0.0, 1.0, 0.);      /* up is in positive Y direction */
  316.   glPushMatrix();       /* dummy push so we can pop on model
  317.                            recalc */
  318.   glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  319.   glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
  320.   glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
  321.   glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
  322.   glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
  323.   glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
  324.   glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor);
  325.   glEnable(GL_LIGHT0);
  326.   glEnable(GL_LIGHT1);
  327.   glutMainLoop();
  328.   return 0;             /* ANSI C requires main to return int. */
  329. }
  330.